#include <dspSimulator/instruction/bnrp.h>


bool BNRP::checkCondition(std::shared_ptr<DspMachine> dspMachine) {
    return checkStandardCondition(dspMachine);
}

void BNRP::loadInstIRIntoJit(llvm::LLVMContext *llvmContext, llvm::Module *module,
                             std::shared_ptr<llvm::IRBuilder<>> irBuilder) {

}

std::shared_ptr<Instruction> BNRP::decode(std::shared_ptr<InstInfo> instInfo, u64 baseCycle) {
    std::shared_ptr<BNRP> bnrp;
    auto dspInstInfo = std::dynamic_pointer_cast<DspInstInfo>(instInfo);
    bool isStandardInst = dspInstInfo->isStandardInstruction();
    if (isStandardInst) {
        auto data = vectorToBitSet<32>(dspInstInfo->getBits());
        if (checkBits<10>(data, 13, 0b0011100000) && checkBits<10>(data, 2, 0b0000111000)) {
            bnrp = std::make_shared<BNRP>(*this);
            bnrp->creg_z = extractBits<4>(data, 28);
            bnrp->dst = extractBits<5>(data, 23).to_ulong();
            bnrp->x = data[12];
            bnrp->s = data[1];
            bnrp->p = data[0];
            bnrp->funcUnit = FuncUnit::S2;
        }
    }
    return bnrp;
}

void BNRP::executeCustom(std::shared_ptr<TargetMachine> targetMachine, ExecutePhase executePhase) {
    if (executePhase == ExecutePhase::E6) {
        // directs the CPU to the proper location to continue program execution after NMI processing
        auto NRP = *targetMachine->getRegisters()->getReg32ByName(
                CRegName[static_cast<u32>(CRegKind::NRP)])->getDataPtr();
        targetMachine->getRegisters()->getReg32ByName("pc")->updateData(NRP);
        // copy the NTSR register to TSR register
        auto NTSR = *targetMachine->getRegisters()->getReg32ByName(
                CRegName[static_cast<u32>(CRegKind::NTSR)])->getDataPtr();
        targetMachine->getRegisters()->getReg32ByName(CRegName[static_cast<u32>(CRegKind::TSR)])->updateData(NTSR);
    }
}

std::string BNRP::toString() const {
    return getStandardConditionString() + " B " + FuncUnitName[static_cast<u32>(funcUnit)] + " NRP";
}

std::shared_ptr<DspInstruction> BNRP::clone() {
    return std::make_shared<BNRP>(*this);
}
